<!--
  文件级注释：角色管理页面
  说明：展示系统角色列表，支持按角色名与组织类型筛选；仅在 H5 项目中编写/修改代码；所有接口调用以返回值 code === 0 判定成功。
  参数：无（组件内部维护筛选参数）
  返回值：无（渲染 UI）
  异常：接口异常会在页面以轻提示/控制台打印形式呈现。
-->
<template>
  <div class="container">
    <h2 class="page-title">角色管理</h2>

    <!-- 筛选区域 -->
    <div class="card filters">
      <div class="filters-row">
        <label class="filter-label">角色名称</label>
        <input v-model="filters.roleName" class="input" placeholder="支持模糊查询" />

        <label class="filter-label">组织类型</label>
        <select v-model.number="filters.orgType" class="input" style="width: 160px">
          <option :value="-1">不限</option>
          <option :value="0">平台</option>
          <option :value="1">商户</option>
          <option :value="2">门店</option>
        </select>

        <button class="btn secondary" @click="onSearch">搜索</button>
        <button class="btn secondary" @click="onReset">重置</button>
      </div>
    </div>

    <!-- 列表区域 -->
    <div class="card">
      <table class="table">
        <thead>
          <tr>
            <th style="width: 36px">#</th>
            <th>角色ID</th>
            <th>角色名称</th>
            <th>角色类型</th>
            <th>组织类型</th>
            <th>描述</th>
            <th>创建时间</th>
          </tr>
        </thead>
        <tbody>
          <tr v-if="loading" class="loading-row">
            <td colspan="7" class="loading"><div class="spinner"></div>加载中...</td>
          </tr>
          <tr v-else-if="displayRoles.length === 0" class="empty-row">
            <td colspan="7" class="empty">暂无数据</td>
          </tr>
          <template v-else>
            <tr v-for="(r, idx) in displayRoles" :key="r.id">
              <td>{{ idx + 1 }}</td>
              <td>{{ r.id || '-' }}</td>
              <td>{{ r.roleName || '-' }}</td>
              <td>
                <span class="badge" :class="roleBadge(r.roleType)">{{ formatRoleType(r.roleType) }}</span>
              </td>
              <td>
                <span class="badge" :class="orgBadge(r.organizationType)">{{ formatOrgType(r.organizationType) }}</span>
              </td>
              <td>{{ r.description || '-' }}</td>
              <td>{{ formatDate(r.creationTime) }}</td>
            </tr>
          </template>
        </tbody>
      </table>
    </div>

    <!-- 轻提示 -->
    <div v-if="toast.show" class="toast" :class="toast.type">{{ toast.text }}</div>
  </div>
  
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, computed } from 'vue'
import { OrganizationService, type RoleItem } from '../services/organization'
import { isSuccess } from '../services/types'

/**
 * 类级注释：Roles 页面组件
 * 负责拉取并展示系统角色列表，提供简单筛选能力。
 */

// 加载状态与角色数据
const loading = ref(false)
const roles = ref<RoleItem[]>([])

// 规范化后的展示数据（兼容大小写字段）
type RoleDisplay = {
  id: string | number
  roleName: string
  roleType?: number
  organizationType?: number
  description?: string
  creationTime?: string
}

/**
 * 函数级注释：规范化角色数据（兼容后端返回的大小写字段）
 * @param r 原始角色对象，可能包含 PascalCase 或 camelCase 字段
 * @returns 统一字段格式的 RoleDisplay 对象
 * @throws 无（安全转换）
 */
function normalizeRole(r: any): RoleDisplay {
  return {
    id: r.Id ?? r.id ?? '-',
    roleName: r.RoleName ?? r.roleName ?? '-',
    roleType: (r.RoleType ?? r.roleType ?? undefined) as number | undefined,
    organizationType: (r.OrganizationType ?? r.organizationType ?? undefined) as number | undefined,
    description: r.Description ?? r.description ?? '-',
    creationTime: r.CreationTime ?? r.creationTime ?? undefined,
  }
}

/**
 * 函数级注释：计算属性，生成用于渲染的规范化角色列表
 * @returns 规范化后的角色列表
 */
const displayRoles = computed<RoleDisplay[]>(() => roles.value.map(normalizeRole))

// 轻提示
const toast = reactive<{ show: boolean; text: string; type: 'success' | 'danger' | 'secondary' }>({ show: false, text: '', type: 'secondary' })

// 筛选参数
const filters = reactive<{ roleName: string; orgType: number }>({ roleName: '', orgType: -1 })

/**
 * 函数级注释：显示轻提示
 * @param text 文本内容
 * @param type 类型（success/danger/secondary）
 * @returns void
 * @throws 无（安全调用）
 */
function showToast(text: string, type: 'success' | 'danger' | 'secondary' = 'secondary'): void {
  toast.text = text
  toast.type = type
  toast.show = true
  setTimeout(() => { toast.show = false }, 2000)
}

/**
 * 函数级注释：格式化日期
 * @param v 原始日期字符串
 * @returns 中文本地时间字符串或 '-'
 * @throws 无（内部 try-catch 防御）
 */
function formatDate(v?: string): string {
  if (!v) return '-'
  try { return new Date(v).toLocaleString('zh-CN') } catch { return v }
}

/**
 * 函数级注释：角色类型文本
 * @param t 角色类型枚举（后端约定的数值）
 * @returns 文本
 */
function formatRoleType(t?: number): string {
  switch (t) {
    case 0: return '平台管理员'
    case 1: return '平台超级管理员'
    case 2: return '店员/成员'
    case 3: return '商户管理员'
    case 4: return '店长'
    case 5: return '医师/技师'
    case 6: return '收银员'
    default: return typeof t === 'number' ? String(t) : '未知'
  }
}

/**
 * 函数级注释：组织类型文本
 * @param t 组织类型（0平台，1商户，2门店）
 * @returns 文本
 */
function formatOrgType(t?: number): string {
  switch (t) {
    case 0: return '平台'
    case 1: return '商户'
    case 2: return '门店'
    default: return typeof t === 'number' ? String(t) : '未知'
  }
}

/**
 * 函数级注释：角色类型徽章样式
 * @param t 角色类型
 * @returns 样式类名
 */
function roleBadge(t?: number): string {
  if (t === 0 || t === 1) return 'primary'
  if (t === 3 || t === 4) return 'success'
  return 'secondary'
}

/**
 * 函数级注释：组织类型徽章样式
 * @param t 组织类型
 * @returns 样式类名
 */
function orgBadge(t?: number): string {
  if (t === 0) return 'primary'
  if (t === 1) return 'warning'
  if (t === 2) return 'info'
  return 'secondary'
}

/**
 * 函数级注释：加载角色列表
 * @returns Promise<void>
 * @throws 可能抛出网络或服务端异常
 */
async function loadRoles(): Promise<void> {
  loading.value = true
  try {
    const dto: { RoleName?: string; OrgTypeList?: number[] } = {}
    if (filters.roleName.trim()) dto.RoleName = filters.roleName.trim()
    if (filters.orgType !== -1) dto.OrgTypeList = [filters.orgType]
    const res = await OrganizationService.getRoleList(dto)
    if (isSuccess(res) && Array.isArray(res.data)) {
      roles.value = res.data as RoleItem[]
    } else {
      roles.value = []
      showToast(res?.message || '获取角色列表失败', 'danger')
    }
  } catch (e: any) {
    roles.value = []
    showToast(e?.message || '接口异常', 'danger')
  } finally {
    loading.value = false
  }
}

/**
 * 函数级注释：搜索（应用筛选）
 * @returns void
 */
function onSearch(): void {
  loadRoles()
}

/**
 * 函数级注释：重置筛选
 * @returns void
 */
function onReset(): void {
  filters.roleName = ''
  filters.orgType = -1
  loadRoles()
}

// 初始化
onMounted(() => {
  loadRoles()
})
</script>

<style scoped>
.page-title { font-size: var(--text-lg); font-weight: 700; margin-bottom: var(--space-4); }
.card { background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4); box-shadow: var(--shadow-sm); margin-bottom: var(--space-4); }
.filters-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.filter-label { color: var(--text-secondary); font-size: var(--text-sm); }
.input { padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); color: var(--text); }
.btn { padding: 8px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-secondary); cursor: pointer; }
.btn.secondary { background: var(--bg-secondary); }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { border-bottom: 1px solid var(--border); padding: 10px; text-align: left; }
.table thead th { background: var(--bg-secondary); font-weight: 600; color: var(--text-secondary); }
.empty { text-align: center; color: var(--text-secondary); padding: var(--space-6); }
.loading { display: flex; align-items: center; gap: var(--space-3); color: var(--text-secondary); }
.spinner { width: 18px; height: 18px; border: 2px solid var(--border); border-top-color: var(--primary); border-radius: 50%; animation: spin 1s linear infinite; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 9999px; font-size: 12px; }
.badge.primary { background: var(--primary-50); color: var(--primary-700); }
.badge.success { background: #e7f6ed; color: #238636; }
.badge.warning { background: #fff4e5; color: #a15c07; }
.badge.info { background: #e5f6ff; color: #075985; }
.badge.secondary { background: var(--bg-secondary); color: var(--text-secondary); }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
